# -*- coding:utf-8 -*-
"""
主窗口视图，组装子组件

"""
from PyQt5.QtGui import QColor, QPainter, QPen, QFontDatabase, QIcon
from PyQt5.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QStackedWidget
from PyQt5.QtCore import Qt, QEvent, QSize
import ctypes

from LibrarySystem.views.login_widget import LoginWidget
from LibrarySystem.views.admin_widget import AdminWidget
from LibrarySystem.views.components.title_bar import TitleBar
from LibrarySystem.views.components.q_signals import q_signals
from LibrarySystem.config.config import Config

# 缩放方位常量
Left, Top, Right, Bottom, LeftTop, RightTop, LeftBottom, RightBottom = range(8)
# 状态栏图标问题
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("PASSLINK")


class MainWindow(QMainWindow):
    """
    @ClassName：MainWindow
    @Description：本项目只创建一个 MainWindow 窗口实例，
    初始化时会将所有页面组装，包括登录、注册页面，以及管理后台页面
    负责无边框状态下，窗口大小伸缩，并将自定义标题栏添加到顶部
    @Author：锦沐Python
    """

    def __init__(self):
        super().__init__()
        # 初始化配置
        self.config = Config()
        # 视图初始化
        self.ui_init()

    def ui_init(self):
        """
        视图初始化
        """
        # 无边框模式，配置鼠标追踪
        self.setMinimumSize(QSize(900, 800))
        # 图标
        self.setWindowIcon(QIcon(self.config.ICON_PATH))
        # 设置背景透明
        self.setAttribute(Qt.WA_TranslucentBackground, True)

        # 设置窗体无边框, 保留状态栏大小化功能
        self.setWindowFlags(
            Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint)

        # 定义边缘用于触发伸缩大小
        self._edge_margins = 5

        # 伸缩方位
        self.Direction = None

        # 左键按下状态
        self._pressed = False

        # 移动
        self.move_drag = False

        # 安装事件过滤器
        self.installEventFilter(self)

        # 加载自定义字体文件
        QFontDatabase.addApplicationFont(self.config.FONT_PATH)

        # 创建子组件
        self.title_bar = TitleBar(self)
        self.login_widget = LoginWidget()
        self.admin_widget = AdminWidget()

        # 创建一个新的 QWidget 作为 主窗口根容器，容纳所有子组件
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        # 创建堆栈窗口，用于装载  LoginWidget  AdminWidget 组件
        self.stackedWidget = QStackedWidget(self)
        self.stackedWidget.addWidget(self.login_widget)
        self.stackedWidget.addWidget(self.admin_widget)
        self.stackedWidget.setCurrentIndex(0)

        # 创建垂直布局，用于装载  TitleBar  QStackedWidget 组件
        self.layout = QVBoxLayout(self.central_widget)
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(self._edge_margins, self._edge_margins, self._edge_margins,
                                       self._edge_margins)  # 去除边距，使控件紧贴边缘
        self.layout.addWidget(self.title_bar)
        self.layout.addWidget(self.stackedWidget)

        # 连接跳转信号，用于页面跳转
        q_signals.LoginToAdmin_Signal.connect(lambda: self.stackedWidget.setCurrentIndex(1))
        q_signals.AdminToLogin_Signal.connect(lambda: self.stackedWidget.setCurrentIndex(0))

        # 递归设置所有子控件的鼠标跟踪
        self.setMouseTrackingRecursive(self, True)

    """
    以下代码仅用于无边框模式，用于移动，缩放窗口
    
    """
    def setMouseTrackingRecursive(self, widget, enable):
        """
        用于迭代子组件，配置数鼠标跟踪模式
        @param widget:  根容器
        @param enable:  追踪开关
        """
        widget.setMouseTracking(enable)
        for child in widget.findChildren(QWidget):
            self.setMouseTrackingRecursive(child, enable)

    def move(self, pos):
        """
        重写父类方法，最大化或者全屏则不允许移动
        @param pos:
        @return:
        """
        if self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen:
            return
        super(MainWindow, self).move(pos)

    def eventFilter(self, obj, event):
        """
        父类方法重写
        @param obj:
        @param event:
        @return:
        """
        if event.type() == QEvent.Enter or event.type() == QEvent.Leave:
            self.setCursor(Qt.ArrowCursor)
            return True
        return super().eventFilter(obj, event)

    def paintEvent(self, event):
        """
        父类方法重写 由于是全透明背景窗口,重绘事件中绘制透明度为1的边框,用于检测边缘
        @param event:
        @return:
        """
        super(MainWindow, self).paintEvent(event)
        painter = QPainter(self)
        painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self._edge_margins))
        painter.drawRect(self.rect())

    def mousePressEvent(self, event):
        """鼠标点击事件"""
        super(MainWindow, self).mousePressEvent(event)
        if event.button() == Qt.LeftButton:
            self._mpos = event.pos()
            self._pressed = True

    def mouseReleaseEvent(self, event):
        '''鼠标弹起事件'''
        super(MainWindow, self).mouseReleaseEvent(event)
        self._pressed = False
        self.Direction = None
        self.setCursor(Qt.ArrowCursor)

    def mouseMoveEvent(self, event):
        """鼠标移动事件"""
        self.setCursor(Qt.ArrowCursor)
        super(MainWindow, self).mouseMoveEvent(event)
        pos = event.pos()
        xPos, yPos = pos.x(), pos.y()
        wm, hm = self.width() - 2 * self._edge_margins, self.height() - 2 * self._edge_margins

        if self.isMaximized() or self.isFullScreen():
            self.Direction = None
            self.setCursor(Qt.ArrowCursor)
            return

        if event.buttons() == Qt.LeftButton and self._pressed:
            self._resizeWidget(pos)
            return

        if xPos <= self._edge_margins and yPos <= self._edge_margins:
            # 左上角
            self.Direction = LeftTop
            self.setCursor(Qt.SizeFDiagCursor)
        elif wm <= xPos <= self.width() and hm <= yPos <= self.height():
            # 右下角
            self.Direction = RightBottom
            self.setCursor(Qt.SizeFDiagCursor)
        elif wm <= xPos and yPos <= self._edge_margins:
            # 右上角
            self.Direction = RightTop
            self.setCursor(Qt.SizeBDiagCursor)
        elif xPos <= self._edge_margins and hm <= yPos:
            # 左下角
            self.Direction = LeftBottom
            self.setCursor(Qt.SizeBDiagCursor)
        elif 0 <= xPos <= self._edge_margins and self._edge_margins <= yPos <= hm:
            # 左边
            self.Direction = Left
            self.setCursor(Qt.SizeHorCursor)
        elif wm <= xPos <= self.width() and self._edge_margins <= yPos <= hm:
            # 右边
            self.Direction = Right
            self.setCursor(Qt.SizeHorCursor)
        elif self._edge_margins <= xPos <= wm and 0 <= yPos <= self._edge_margins:
            # 上面
            self.Direction = Top
            self.setCursor(Qt.SizeVerCursor)
        elif self._edge_margins <= xPos <= wm and hm <= yPos <= self.height():
            # 下面
            self.Direction = Bottom
            self.setCursor(Qt.SizeVerCursor)

    def _resizeWidget(self, pos):
        """调整窗口大小"""
        if self.Direction is None:
            return
        mpos = pos - self._mpos
        xPos, yPos = mpos.x(), mpos.y()
        geometry = self.geometry()
        x, y, w, h = geometry.x(), geometry.y(), geometry.width(), geometry.height()
        if self.Direction == LeftTop:  # 左上角
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
        elif self.Direction == RightBottom:  # 右下角
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mpos = pos
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mpos = pos
        elif self.Direction == RightTop:  # 右上角
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mpos.setX(pos.x())
        elif self.Direction == LeftBottom:  # 左下角
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mpos.setY(pos.y())
        elif self.Direction == Left:  # 左边
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            else:
                return
        elif self.Direction == Right:  # 右边
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mpos = pos
            else:
                return
        elif self.Direction == Top:  # 上面
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
            else:
                return
        elif self.Direction == Bottom:  # 下面
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mpos = pos
            else:
                return

        self.setGeometry(x, y, w, h)
